package com.zhangxun.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangxun.doc.ProdEs;
import com.zhangxun.domain.*;
import com.zhangxun.mapper.SkuMapper;
import com.zhangxun.service.ProdCommService;
import com.zhangxun.service.ProdService;
import com.zhangxun.mapper.ProdMapper;
import com.zhangxun.service.ProdTagReferenceService;
import com.zhangxun.service.SkuService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author 张循
* @description 针对表【prod(商品)】的数据库操作Service实现
* @createDate 2023-01-01 18:04:15
*/
@Service
public class ProdServiceImpl extends ServiceImpl<ProdMapper, Prod>
    implements ProdService{

    @Autowired
    private ProdMapper prodMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private ProdCommService prodCommService;


    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    private SkuService skuService;

    @Autowired
    private ProdTagReferenceService prodTagReferenceService;


    /**
     * 通过分页和查询条件查询商品信息
     * @param page 分页参数
     * @param prod 查询条件
     * @return
     */
    @Override
    public Page<Prod> pageByCondition(Page<Prod> page, Prod prod) {
        Page<Prod> prodPage = prodMapper.selectPage(page, new LambdaQueryWrapper<Prod>()
                .like(StringUtils.hasText(prod.getProdName()), Prod::getProdName, prod.getProdName())
                .eq(prod.getStatus() != null, Prod::getStatus, prod.getStatus()));
        return prodPage;
    }


    /**
     * 保存新增的商品信息
     * @param prod
     * @return
     */
    @Override
    @Transactional
    public boolean saveProd(Prod prod) {
        prod.setDeliveryMode(JSON.toJSONString(prod.getDeliveryModeVo()));
        prod.setCreateTime(new Date());
        prodMapper.insert(prod);//保存商品信息，获取新增记录的id
        Long prodId = prod.getProdId();

        //获取sku，设置商品id和名称，和记录时间，并保存
        List<Sku> skuList = prod.getSkuList();
        skuList.stream().forEach(sku->{
            sku.setProdId(prodId);
            sku.setProdName(prod.getProdName());
            sku.setRecTime(new Date());
        });

       skuService.saveBatch(skuList);

       //获取标签记录转换类型为标签对象集合，并填充数据，然后保存
        List<Long> tagList = prod.getTagList();
        List<ProdTagReference> referenceList = tagList.stream().map(tagId -> {
            ProdTagReference prodTagReference = new ProdTagReference();
            prodTagReference.setProdId(prodId);
            prodTagReference.setCreateTime(new Date());
            prodTagReference.setTagId(tagId);
            prodTagReference.setStatus(1);
            return prodTagReference;
        }).collect(Collectors.toList());
      boolean b = prodTagReferenceService.saveBatch(referenceList);

      return b;
    }

    /**
     * 通过分页条件查询商品，并给商品信息赋值，然后导入到es
     * @param current
     * @param size
     */
    @Override
    public void importToES(Integer current, Integer size,Date startDate,Date endDate) {
        //分页查询未上架的商品
        Page<Prod> page = new Page(current,size);
        Page<Prod> prodPage = prodMapper.selectPage(page,
                new LambdaQueryWrapper<Prod>().eq(Prod::getStatus, 0)
                        .between(ObjectUtil.isNotNull(startDate) &&ObjectUtil.isNotNull(endDate)
                                ,Prod::getCreateTime,startDate,endDate));
        List<Prod> prodList = prodPage.getRecords();

        //判断是否查询到了数据
        if(CollectionUtils.isEmpty(prodList)){
            return;
        }
        //给商品设置好评数和好评率
        setPraiseNumAndPositiveRat(prodList);
        //给商品设置标签id
        setTagIdByProdId(prodList);

        //将商品对象复制到导入的es对象当中
        List<ProdEs> prodEsList = prodList.stream().map(prod -> {
            prod.setStatus(1);
            ProdEs prodEs = new ProdEs();
            BeanUtils.copyProperties(prod, prodEs);
            return prodEs;
        }).collect(Collectors.toList());
        //导入es
        elasticsearchRestTemplate.save(prodEsList);

        //将导入es中的商品的装上架状态改为已上架
        updateBatchById(prodList);

    }

    /**
     * 通过id和count修改prod和sku库存的方法
     * 如果是购买count为负数。
     * 如果是退货回退库存count为正数。
     *
     * @param changeDto 封装数据的对象
     */
    @Override
    public void updateCountByIds(ChangeDto changeDto) {

        //遍历商品集合获取每个商品的id和修改的数量
        changeDto.getProdChangeList().forEach(prodChange -> {
            prodMapper.updateCountById(prodChange);
        });

        //遍历sku集合获取每个sku的id和修改的数量
        changeDto.getSkuChangeList().forEach(skuChange->{
            skuMapper.updateCountById(skuChange);
        });


    }

    /**
     * 设置商品好评数和好评率的方法
     *
     * @param prodList
     */
    private void setPraiseNumAndPositiveRat(List<Prod> prodList) {
        //获取商品id集合
        List<Long> prodIdList = prodList.stream().map(Prod::getProdId).collect(Collectors.toList());

        //通过标签id查询出对应的所有的评价
        List<ProdComm> commList = prodCommService.list(new LambdaQueryWrapper<ProdComm>().in(ProdComm::getProdId, prodIdList));

        //判断商品目前是否有评价
        if (CollectionUtils.isEmpty(commList)) {
            return;
        }

        //根据商品id对评价进行分组
        Map<Long, List<ProdComm>> map = commList.stream().collect(Collectors.groupingBy(ProdComm::getProdId));

        //给每个商品设置好评率和好评数
        prodList.stream().forEach(prod -> {

            //获取商品对应的评论集合
            List<ProdComm> prodComms = map.get(prod.getProdId());

            //如果对应的商品有评价就设置到商品中去
            if (!CollectionUtils.isEmpty(prodComms)) {
                //计算好评的数量
                long count = prodComms.stream().filter(comm -> comm.getEvaluate() == 0).count();

                //计算商品的好评率
                int size = prodComms.size();
                long positiveRating = count % size == 0 ? (count / size) : (count / size + 1);
                BigDecimal rating = new BigDecimal(positiveRating * 100);
                BigDecimal lastRating = rating.setScale(0, BigDecimal.ROUND_HALF_UP);

                //设置好评数和好评率
                prod.setPraiseNumber(count);
                prod.setPositiveRating(lastRating);
            }
        });

    }

    /**
     * 给每个商品设置标签的方法
     *
     * @param prodList
     */
    private void setTagIdByProdId(List<Prod> prodList) {
        //获取商品id集合
        List<Long> prodIdList = prodList.stream().map(Prod::getProdId).collect(Collectors.toList());
        //查询对应商品的所有标签
        List<ProdTagReference> referenceList = prodTagReferenceService.list(new LambdaQueryWrapper<ProdTagReference>()
                .in(ProdTagReference::getProdId, prodIdList));

        //根据商品id进行分组
        Map<Long, List<ProdTagReference>> map = referenceList.stream().collect(Collectors.groupingBy(ProdTagReference::getProdId));

        //给所有商品设置标签
        prodList.stream().forEach(prod -> {
            //通过商品的id获取map中对应的标签对象集合，并转换为标签id集合
            List<ProdTagReference> references = map.get(prod.getProdId());
            if(!CollectionUtils.isEmpty(references)) {
                List<Long> tagIdList = references
                        .stream().map(ProdTagReference::getTagId).collect(Collectors.toList());
                prod.setTagList(tagIdList);
            }
        });

    }



}




